#
# SQL actions translated into Neon atomic operations
#
import logging

import atom
import version

log = logging.getLogger('sql_adapt')

#
# BEGIN...COMMIT
#
# Guarrantees atomic tranactions on a per-atom basis only
#

#
# SELECT
#
# we don't handle these for the time being. later on, there should be
# some kind of analyzer which flags for potential conflicts, etc.
#

#
# INSERT ATOM
#

#
# XXX/bowei -- need some way to merge conflicted objects?
#
# INSERT
#
# 2.1.1 create new guid, perform put_atom
# 2.2 No conflict
#
# 2.2.1 create new guid, update VV to override old atom, put_atom
# 2.3 Multiple (conflict)
# 2.3.1 Fail INSERT
class InsertDesc:
    def __init__(self, tablename, cols, values):
        self.table = tablename
        self.columns = cols
        self.values = values

class Adapter:
    def __init__(self, neon_inst):
        self.neon_ = neon_inst
        self.atom_store_ = self.neon_.atom_store()
        self.db_ = self.atom_store_.db()

    def exec_sql(self, sql_text):
        """Execute a SQL statement, translating the statement
        appropriately to the Neon statements."""
        self.insert(InsertDesc('test', None, [None, 'a']))
        
    def insert(self, insert_desc):
        log.debug('insert(%s)' % insert_desc)
        # find type
        types = self.atom_store_.get_types_from_table(insert_desc.table)
        if len(types) == 0:
            return
        if len(types) > 1:
            raise NotImplemented()
        
        # XXX/bowei -- don't handle multiple tables right now
        new_atom = atom.Atom(types[0])
        g = self.atom_store_.get_new_guid()
        vv = version.Vector([g.as_tuple()])
        new_atom.set_guid(g)
        new_atom.set_version(vv)

        # setup the fields appropriately
        all_columns = self.db_.table_schema(insert_desc.table)
        if insert_desc.columns == None:
            insert_desc.columns = all_columns
            row = dict(zip(all_columns, insert_desc.values))
            # how to handle this?
            row['guid'] = str(new_atom.get_guid())
        else:
            # There are some missing columns...
            raise NotImplemented()
        new_atom.fields = {insert_desc.table : [row]}

        log.debug('insert atom=%s' % new_atom)
        self.atom_store_.put_atom(new_atom)

#
# UPDATE
#
# 1. Use intersection query to any conflicts
# 2.1 No atoms
# 2.1.1 Fail UPDATE
# 2.2 No conflict
# 2.2.1 create new guid, update VV to override, put_atom
# 2.3 Conflict
# 2.3.1 Fail UPDATE
#

#
# DELETE
#
# XXX/bowei -- what about conflicts?
#
# 1. Use query to find atoms to remove
# 2.1 mark all with delete tombstone with new VV
# 2.2 get rid of row information
#

#
# MERGE
#
# This is a new keyword only Neon supports
#
# MERGE [  BY GUID  (guid list)
#        | BY QUERY (where query) ] 
#       [  DIFF (only the conflicting fields (?))
#        | VALUES (all values to put in atom)]
#
